package com.uduemc.biso.node.module.common.service.impl;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.formdata.ComponentFormData;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.formdata.ContainerFormData;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.formdata.componentdata.ComponentFormDataItemDelete;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.formdata.componentdata.ComponentFormDataItemUpdate;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.formdata.containerdata.ContainerFormDataItemDelete;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.formdata.containerdata.ContainerFormDataItemInsert;
import com.uduemc.biso.node.core.common.entities.publishdata.databody.formdata.containerdata.ContainerFormDataItemUpdate;
import com.uduemc.biso.node.core.entities.SComponentForm;
import com.uduemc.biso.node.core.entities.SContainerForm;
import com.uduemc.biso.node.core.entities.SForm;
import com.uduemc.biso.node.module.common.service.CFormContainerService;
import com.uduemc.biso.node.module.service.SComponentFormService;
import com.uduemc.biso.node.module.service.SContainerFormService;

import cn.hutool.core.collection.CollectionUtil;

@Service
public class CFormContainerServiceImpl implements CFormContainerService {

	private final static Logger logger = LoggerFactory.getLogger(CFormContainerServiceImpl.class);

	@Autowired
	private SContainerFormService sContainerFormServiceImpl;

	@Autowired
	private SComponentFormService sComponentFormServiceImpl;

	@Transactional
	@Override
	public void publish(long hostId, long siteId, ContainerFormData scontainerForm, ComponentFormData scomponentForm,
			ThreadLocal<Map<String, Long>> containerFormTmpIdHolder) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {

		Map<String, Long> containerFormTmpId = containerFormTmpIdHolder.get();

		List<ContainerFormDataItemInsert> insertList = scontainerForm.getInsert();

		List<ContainerFormDataItemUpdate> updateList = scontainerForm.getUpdate();

		List<ContainerFormDataItemDelete> deleteList = scontainerForm.getDelete();

		logger.info(insertList.toString());

		insertList(hostId, siteId, insertList, containerFormTmpId);

		updateList(hostId, siteId, updateList, containerFormTmpId);

		deleteList(hostId, siteId, deleteList, scomponentForm);
	}

	@Transactional
	@Override
	public void insertList(long hostId, long siteId, List<ContainerFormDataItemInsert> containerFormDataItemInsertList, Map<String, Long> containerFormTmpId) {
		if (CollectionUtils.isEmpty(containerFormDataItemInsertList)) {
			return;
		}
		// 表单容器 tempId 数据集
		Iterator<ContainerFormDataItemInsert> iterator = containerFormDataItemInsertList.iterator();
		while (iterator.hasNext()) {
			ContainerFormDataItemInsert containerFormDataItemInsert = iterator.next();
			SContainerForm sContainerForm = containerFormDataItemInsert.getSContainerForm(hostId, siteId, containerFormTmpId);

			if (sContainerForm == null) {
				throw new RuntimeException(
						"通过 containerFormDataItemInsert 获取 sContainerForm 数据失败 containerFormDataItemInsert： " + containerFormDataItemInsert.toString());
			}

			SContainerForm insert = sContainerFormServiceImpl.insert(sContainerForm);
			if (insert == null) {
				throw new RuntimeException("写入数据失败，sContainerForm ： " + sContainerForm.toString());
			}

			containerFormTmpId.put(containerFormDataItemInsert.getTmpId(), insert.getId());

			List<ContainerFormDataItemInsert> children = containerFormDataItemInsert.getChildren();
			if (!CollectionUtils.isEmpty(children)) {
				insertList(hostId, siteId, children, containerFormTmpId);
			}
		}
	}

	@Transactional
	@Override
	public void updateList(long hostId, long siteId, List<ContainerFormDataItemUpdate> containerFormDataItemUpdateList, Map<String, Long> containerFormTmpId) {
		if (CollectionUtils.isEmpty(containerFormDataItemUpdateList)) {
			return;
		}
		// 更新
		Iterator<ContainerFormDataItemUpdate> iteratorUpdate = containerFormDataItemUpdateList.iterator();
		while (iteratorUpdate.hasNext()) {

			ContainerFormDataItemUpdate containerFormDataItemUpdate = iteratorUpdate.next();

			SContainerForm sContainerForm = containerFormDataItemUpdate.getSContainerForm(hostId, siteId, containerFormTmpId);

			if (sContainerForm == null) {
				throw new RuntimeException(
						"通过 containerFormDataItemUpdate 获取 sContainerForm 数据为空 containerFormDataItemUpdate： " + containerFormDataItemUpdate.toString());
			}

			// 验证id
			if (!sContainerFormServiceImpl.isExist(sContainerForm.getId(), sContainerForm.getHostId(), sContainerForm.getSiteId(),
					sContainerForm.getFormId())) {
				throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainerForm 验证id数据不存在 sContainerForm： " + sContainerForm.toString());
			}

			if (sContainerForm.getParentId() == null) {
				throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainerForm 验证parentId数据为空 sContainerForm： " + sContainerForm.toString());
			}

			// 验证parentId
			if (sContainerForm.getParentId().longValue() > 0) {
				if (!sContainerFormServiceImpl.isExist(sContainerForm.getParentId(), sContainerForm.getHostId(), sContainerForm.getSiteId(),
						sContainerForm.getFormId())) {
					throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainerForm 验证parentId数据不存在 sContainerForm： " + sContainerForm.toString());
				}
			}

			if (sContainerForm.getBoxId() == null) {
				throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainerForm 验证boxId数据为空 sContainerForm： " + sContainerForm.toString());
			}

			// 验证parentId
			if (sContainerForm.getBoxId().longValue() > 0) {
				if (!sContainerFormServiceImpl.isExist(sContainerForm.getBoxId(), sContainerForm.getHostId(), sContainerForm.getSiteId(),
						sContainerForm.getFormId())) {
					throw new RuntimeException("通过 containerDataItemUpdate 获取 sContainerForm 验证boxId数据不存在 sContainerForm： " + sContainerForm.toString());
				}
			}

			SContainerForm update = sContainerFormServiceImpl.updateById(sContainerForm);

			if (update == null || update.getId().longValue() != sContainerForm.getId().longValue()) {
				throw new RuntimeException("对 sContainerForm 数据进行更新失败： " + sContainerForm.toString());
			}

		}
	}

	@Transactional
	@Override
	public void deleteList(long hostId, long siteId, List<ContainerFormDataItemDelete> containerFormDataItemDeleteList, ComponentFormData scomponentForm) {
		if (CollectionUtils.isEmpty(containerFormDataItemDeleteList)) {
			return;
		}
		// TODO Auto-generated method stub
		Iterator<ContainerFormDataItemDelete> iteratorDelete = containerFormDataItemDeleteList.iterator();
		while (iteratorDelete.hasNext()) {
			ContainerFormDataItemDelete containerFormDataItemDelete = iteratorDelete.next();
			SContainerForm findOne = sContainerFormServiceImpl.findOne(containerFormDataItemDelete.getId());
			// 验证 id
			if (findOne == null || findOne.getId() == null || findOne.getHostId() == null || findOne.getSiteId() == null
					|| findOne.getHostId().longValue() != hostId || findOne.getSiteId().longValue() != siteId) {
				throw new RuntimeException(
						"通过 containerFormDataItemDelete的id 获取 SContainerForm 失败 containerFormDataItemDelete： " + containerFormDataItemDelete.toString());
			}

			if (findOne.getTypeId() != null || findOne.getTypeId().longValue() == 7L) {
				// 删除的如果是一个容器组件，则该容器组件中不能存在展示组件，或者展示组件也在此次删除当中
				SComponentForm sComponentForm = sComponentFormServiceImpl.findOneByContainerIdStatus(hostId, siteId, findOne.getId(), (short) 0);
				if (sComponentForm != null) {
					List<ComponentFormDataItemDelete> componentFormDataItemDeleteList = scomponentForm.getDelete();
					// 是否在删除的列表中
					boolean isExistInDelList = false;
					if (!CollectionUtils.isEmpty(componentFormDataItemDeleteList)) {
						for (ComponentFormDataItemDelete componentFormDataItemDelete : componentFormDataItemDeleteList) {
							if (componentFormDataItemDelete != null && componentFormDataItemDelete.getId() == sComponentForm.getId().longValue()) {
								isExistInDelList = true;
								break;
							}
						}
					}
					List<ComponentFormDataItemUpdate> componentFormDataItemUpdateList = scomponentForm.getUpdate();
					// 是否在更新的列表中
					boolean isExistInUpdList = false;
					if (!CollectionUtils.isEmpty(componentFormDataItemUpdateList)) {
						for (ComponentFormDataItemUpdate componentFormDataItemUpdate : componentFormDataItemUpdateList) {
							if (componentFormDataItemUpdate != null && componentFormDataItemUpdate.getId() == sComponentForm.getId().longValue()) {
								isExistInUpdList = true;
								break;
							}
						}
					}

					if (!isExistInDelList && !isExistInUpdList) {
						throw new RuntimeException("数据库 s_component_form 表中存在此次需要删除的容器组件ID， 同时展示组件不在本次删除数据当中， 也不在本次更新的数据当中！");
					}
				}
			}

			// 是否存在已改容器组件作为父级的数据存在，并且该数据还不在本次删除的数据当中
			List<SContainerForm> parentSContainerForm = sContainerFormServiceImpl.findByParentIdAndStatus(hostId, siteId, findOne.getId(), (short) 0);
			if (CollectionUtil.isNotEmpty(parentSContainerForm)) {
				for (SContainerForm parent : parentSContainerForm) {
					// 验证是否存在此次删除的数据当中
					boolean isExistInDel = false;
					for (ContainerFormDataItemDelete delete : containerFormDataItemDeleteList) {
						if (delete.getId() == parent.getId().longValue()) {
							isExistInDel = true;
							break;
						}
					}
					if (!isExistInDel) {
						throw new RuntimeException("数据库 s_container_form 表中存在此次需要删除的子容器组件ID， 同时子容器组件不在本次删除数据当中！");
					}
				}

			}

			findOne.setStatus((short) 4);
			SContainerForm updateAllById = sContainerFormServiceImpl.updateById(findOne);
			if (updateAllById == null || updateAllById.getId() == null || updateAllById.getId().longValue() != containerFormDataItemDelete.getId()) {
				throw new RuntimeException("通过 查询出来的 findOne 更新 statue 为4进行删除失败，findOne： " + findOne.toString());
			}
		}
	}

	@Override
	public void delete(SForm sForm) {
		sContainerFormServiceImpl.deleteByHostFormId(sForm.getHostId(), sForm.getId());
	}
}
